#include "Physics.h"
#include "Collider.h"

Tile* Physics::IsCollidingStatic(Tile* map, int width, int height, Collider* player, Axis axis)
{
	Tile* result = 0;
	int * mapCoordinates = map->GetCollider()->GetCoordinates();
	int tileSize = mapCoordinates[2] - mapCoordinates[0];
	delete(mapCoordinates);
	int playerWidth, playerHeight;
	int * playerCoordinates = player->GetCoordinates();
	playerWidth = playerCoordinates[2] - playerCoordinates[0];
	playerHeight = playerCoordinates[3] - playerCoordinates[1];
	delete(playerCoordinates);
	for (int i = 0; i < width*height; i++)
	{
		int * tileCoordinates = map[i].GetCollider()->GetCoordinates();
		int * playerCoordinates = player->GetCoordinates();

		int tileX0 = tileCoordinates[0];
		int tileY0 = tileCoordinates[1];
		int tileXF = tileCoordinates[2];
		int tileYF = tileCoordinates[3];

		int playerX0 = playerCoordinates[0];
		int playerY0 = playerCoordinates[1];
		int playerXF = playerCoordinates[2];
		int playerYF = playerCoordinates[3];

		delete(tileCoordinates);
		delete(playerCoordinates);

		if (tileY0 > playerYF) break;
		switch (axis)
		{
			case Physics::Vertical:
				if (((tileY0 <= playerYF && tileY0 > playerY0) || (playerY0 <= tileYF && playerYF > tileYF)) && ((tileXF > playerX0 && tileX0 < playerX0) || (tileX0 < playerXF && tileXF > playerXF)))
					result = map[i].GetCollider()->Collides(player) ? &map[i] : 0;
				break;
			case Physics::Horizontal:
				if (((tileX0 <= playerXF && tileX0 > playerX0) || (tileXF >= playerX0 && tileXF < playerYF)) && ((tileYF > playerY0 && tileY0 < playerY0) || (tileY0 < playerYF && tileYF > playerYF)))
					result = map[i].GetCollider()->Collides(player) ? &map[i] : 0;
				break;
			case Physics::All:
				result = map[i].GetCollider()->Collides(player) ? &map[i] : 0;
				break;
			case Physics::HorizontalPositive:
				if ((tileX0 <= playerXF && tileX0 > playerX0) && ((tileYF > playerY0 && tileYF < playerYF) || (tileY0 < playerYF && tileY0 > playerY0)))
					result = map[i].GetCollider()->Collides(player) ? &map[i] : 0;
				break;
			case Physics::HorizontalNegative:
				if ((tileXF >= playerX0 && tileXF < playerXF) && ((tileYF > playerY0 && tileYF < playerYF) || (tileY0 < playerYF && tileY0 > playerY0)))
					result = map[i].GetCollider()->Collides(player) ? &map[i] : 0;
				break;
			case Physics::VerticalPositive:
				if ((tileY0 <= playerYF && tileY0 > playerY0) && ((tileXF > playerX0 && tileXF < playerXF) || (tileX0 < playerXF && tileX0 > playerX0)))
					result = map[i].GetCollider()->Collides(player) ? &map[i] : 0;
				break;
			case Physics::VerticalNegative:
				if ((playerY0 <= tileYF && playerYF > tileYF) && ((tileXF > playerX0 && tileXF < playerXF) || (tileX0 < playerXF && tileX0 > playerX0)))
					result = map[i].GetCollider()->Collides(player) ? &map[i] : 0;
				break;
		}
		if (result != 0) return result;
	}
	return result;
}

Collider* Physics::IsCollidingDynamic(Collider* collider, Physics::Axis axis)
{
	Collider * result = 0;
	for (int i = 0; i < m_dynamicObjects.size(); ++i)
	{
		if (m_dynamicObjects[i] && collider->GetType() != m_dynamicObjects[i]->GetType())
		{
			int* object1Coordinates = collider->GetCoordinates();
			int* object2Coordinates = m_dynamicObjects[i]->GetCoordinates();
			int object1X0 = object1Coordinates[0];
			int object1Y0 = object1Coordinates[1];
			int object1XF = object1Coordinates[2];
			int object1YF = object1Coordinates[3];

			int object2X0 = object2Coordinates[0];
			int object2Y0 = object2Coordinates[1];
			int object2XF = object2Coordinates[2];
			int object2YF = object2Coordinates[3];
			delete(object1Coordinates);
			delete(object2Coordinates);

			switch (axis)
			{
			case Physics::Vertical:
				if (((object1Y0 <= object2YF && object1Y0 > object2Y0) || (object2Y0 <= object1YF && object2YF > object1YF)) && ((object1XF > object2X0 && object1X0 < object2X0) || (object1X0 < object2XF && object1XF > object2XF)))
					result = m_dynamicObjects[i]->Collides(collider) ?  m_dynamicObjects[i] : 0;
				break;
			case Physics::Horizontal:
				if (((object1X0 <= object2XF && object1X0 > object2X0) || (object1XF >= object2X0 && object1XF < object2YF)) && ((object1YF > object2Y0 && object1Y0 < object2Y0) || (object1Y0 < object2YF && object1YF > object2YF)))
					result = m_dynamicObjects[i]->Collides(collider) ?  m_dynamicObjects[i] : 0;
				break;
			case Physics::All:
				result = m_dynamicObjects[i]->Collides(collider) ?  m_dynamicObjects[i] : 0;
				break;
			case Physics::HorizontalPositive:
				if ((object1X0 <= object2XF && object1X0 > object2X0) && ((object1YF > object2Y0 && object1YF < object2YF) || (object1Y0 < object2YF && object1Y0 > object2Y0)))
					result = m_dynamicObjects[i]->Collides(collider) ?  m_dynamicObjects[i] : 0;
				break;
			case Physics::HorizontalNegative:
				if ((object1XF >= object2X0 && object1XF < object2XF) && ((object1YF > object2Y0 && object1YF < object2YF) || (object1Y0 < object2YF && object1Y0 > object2Y0)))
					result = m_dynamicObjects[i]->Collides(collider) ?  m_dynamicObjects[i] : 0;
				break;
			case Physics::VerticalPositive:
				if ((object1Y0 <= object2YF && object1Y0 > object2Y0) && ((object1XF > object2X0 && object1XF < object2XF) || (object1X0 < object2XF && object1X0 > object2X0)))
					result = m_dynamicObjects[i]->Collides(collider) ?  m_dynamicObjects[i] : 0;
				break;
			case Physics::VerticalNegative:
				if ((object2Y0 <= object1YF && object2YF > object1YF) && ((object1XF > object2X0 && object1XF < object2XF) || (object1X0 < object2XF && object1X0 > object2X0)))
					result = m_dynamicObjects[i]->Collides(collider) ?  m_dynamicObjects[i] : 0;
				break;
			}
			if (result) return result;
		}
	}
	return result;
}

bool Physics::AddDynamicObject(Collider* collider)
{
	if (m_dynamicObjectsCount < 20)
	{
		for (int i = 0; i < m_dynamicObjects.size(); ++i)
		{
			if (!m_dynamicObjects[i])
			{
				m_dynamicObjects[i] = collider;
				m_dynamicObjectsCount++;
				return true;
			}
		}
	}
	return false;
}

bool Physics::RemoveDynamicObject(Collider* collider)
{
	for (int i = 0; i < m_dynamicObjects.size(); ++i)
	{
		if (m_dynamicObjects[i])
		{
			if (m_dynamicObjects[i] == collider)
			{
				m_dynamicObjects[i] = 0;
				m_dynamicObjectsCount--;
				return true;
			}
		}
	}
}


std::vector<Collider*> Physics::m_dynamicObjects = std::vector<Collider *>(20, 0);
int Physics::m_dynamicObjectsCount = 0;